#include <stdio.h>
#include <assert.h>
#include <pthread.h>
#include <stdlib.h>

struct fib {
  int n;
  long long result;
};


void * fibo_n(void *arg) {

  struct fib *f = (struct fib *)arg;
  
  if(f->n <= 1)
    f->result = f->n;
  
  if(f->n > 1) {

    pthread_t t1, t2;
    
    struct fib *f1,*f2;
    f1 = malloc(sizeof(struct fib));
    f2 = malloc(sizeof(struct fib));
    long long *ret1 = malloc(sizeof(*ret1));
    long long *ret2 = malloc(sizeof(*ret2));
    
    f1->n = f->n - 1;
    f2->n = f->n - 2;
    f1->result = 0;
    f2->result = 0;

    pthread_create(&t1, NULL, fibo_n, (void*)f1); 
    pthread_create(&t2, NULL, fibo_n, (void*)f2);

    pthread_join(t1, (void **)ret1);
    pthread_join(t2, (void **)ret2);
 
    f->result = f1->result + f2->result;
    //printf("n: %d | result apres calcul: %lld\n", f->n, f->result);
  }

  pthread_exit(NULL);
}


int main(int argc, char* argv[]) {

  if(argc < 2) {
    printf("Vous n'avez pas entre une valeur pour n. \nLe calcul de fibo(n) ne peut se faire.\n");
    return 1;
  }

  struct fib *f;
  long long *result = malloc(sizeof(result));
  pthread_t t;
  f= malloc(sizeof(struct fib));
  f->n = atoi(argv[1]);
  f->result = 0;

  pthread_create(&t, NULL, fibo_n, (void*)f); 
  pthread_join(t, (void **)result);

  printf("Resultat fibo(%d) = %lld\n", f->n, f->result);
  
  return EXIT_SUCCESS;

}
